package com.yin.myproject.distributedlock;

import org.I0Itec.zkclient.ZkClient;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 锁接口的具体实现，主要借助于继承的父类BaseDistributedLock来实现的接口方法
 *
 * @author Eason
 * @create 2018-03-06 15:28
 **/
public class SimpleDistributedLockMutex extends BaseDistributedLock implements DistributedLock {

    //锁名称的前缀
    private static final String LOCK_NAME = "lock-";
    //用于保存Zookeeper中实现分布式锁的节点，如名称为locker：/locker，该节点应该是持久节点，在该节点下面创建临时顺序节点来实现分布式锁
    private final String basePath;
    //用于保存某个客户端在locker下面创建成功的顺序节点，用于后续相关操作使用（如判断）
    private String ourLockPath;

    public SimpleDistributedLockMutex(ZkClient client, String basePath) {
        //调用父类的构造方法在Zookeeper中创建basePath节点，并且为basePath节点子节点设置前缀同时保存basePath的引用给当前类属性
        super(client, basePath, LOCK_NAME);
        this.basePath = basePath;
    }

    @Override
    public void acquire() throws Exception {
        //-1表示不设置超时时间，超时由Zookeeper决定
        if (!internalLock(-1, null)) {
            throw new IOException("连接丢失!在路径:'" + basePath + "'下不能获取锁!");
        }
    }

    /**
     * 用于获取锁资源，通过父类的获取锁方法来获取锁
     *
     * @param time 获取锁的超时时间
     * @param unit time的时间单位
     * @throws Exception
     * @return是否获取到锁
     */

    private boolean internalLock(long time, TimeUnit unit) throws Exception {
        //如果ourLockPath不为空则认为获取到了锁，具体实现细节见attemptLock的实现
        ourLockPath = attemptLock(time, unit);
        return ourLockPath != null;
    }
    /**
     * 获取锁，带有超时时间
     */
    @Override
    public boolean acquire(long time, TimeUnit timeUnit) throws Exception {
        return internalLock(time, timeUnit);
    }

    @Override
    public void release() throws Exception {
        releaseLock(ourLockPath);
    }
}
